Spatio-temporal accessibility analysis using the 2SFCA methodology - Ivor Mardesic

In this Markdown document the 2SFCA methodology is implemented on the example of accessibility to hospitals for the citizens of the City of Zurich.

Prepare workspace

We will use three R packages.

Sf for managing spatial data. tmap for visualizations. cppRouting for calculating isochrones for points of interest.

## Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1

Import data

Zurich hospitals

Road network

Zurich Stadtkreise

Demographic data - GIUZ server

## Reading layer `stzh.adm_stadtkreise_a_polygon' from data source `C:\Users\Ivor\Documents\R\Projects\2SFCA\Data\kreise\data\stzh.adm_stadtkreise_a_polygon.shp' using driver `ESRI Shapefile'
## Simple feature collection with 12 features and 4 fields
## geometry type:  POLYGON
## dimension:      XY
## bbox:           xmin: 2676225 ymin: 1241584 xmax: 2689666 ymax: 1254306
## projected CRS:  CH1903+ / LV95
## Reading layer `stzh.poi_spital_view_point' from data source `C:\Users\Ivor\Documents\R\Projects\2SFCA\Data\spital\data' using driver `ESRI Shapefile'
## Simple feature collection with 125 features and 52 fields
## geometry type:  POINT
## dimension:      XY
## bbox:           xmin: 2679827 ymin: 1244823 xmax: 2685967 ymax: 1251932
## projected CRS:  CH1903+ / LV95
## Warning: attribute variables are assumed to be spatially constant throughout all
## geometries
## Reading layer `TBA_STR_ACHS_L' from data source `C:\Users\Ivor\Documents\R\Projects\2SFCA\Data\MSc\Strassenentz\strasen\Strassennetz\TBA_STR_ACHS_L.shp' using driver `ESRI Shapefile'
## Simple feature collection with 2614 features and 10 fields
## geometry type:  LINESTRING
## dimension:      XY
## bbox:           xmin: 2668981 ymin: 1239533 xmax: 2693057 ymax: 1258605
## projected CRS:  CH1903+ / LV95
## tmap mode set to interactive viewing
## Legend for symbol sizes not available in view mode.

Data pre-processing

Before we can implement the 2sfca, the data has to be of an appropriate format and depth. We need to prepare the road network dataset for calculating isochrones; catchment areas reachable from a location within a given time budget and network speeds.

The implementation of isochrones will be done using the cppRouting package which integrates the theories of Edger Dijkstra, who worked with and developed graph theory applications in computer science. The Dijkstra algorithm is used for routing between points on a network and is well established in transport sciences; and subsequently, very efficient. The cppRouting package integrates it with R and with some workarounds, we can implement it with spatial data.

Before we can develop isochrones we cannot do the 2SFCA methodology.

Furthermore, for proper isochronal analysis we need to know, for each service and demand point, what is the closest road and “snap” this point of interest to that road.

Road network vertices

The road network is a list of all roads with their geometry. We have to find where do the geometries interesct and declare these intersections as a vertex per the graph theory (a graph is a set of edges and vertices). We have to save in the road network the start and end vertex of a road (edge) as the index of the vertices in a separate spatial data frame. The vertices dataframe will contain the PK (the index) and the X and Y coordinate of the vertex.

In our dataset, every start and end coordinate of a line is a vertex. We need to extract these, assign them a unique ID, and record which edges share them to remove duplicates.

## tmap mode set to interactive viewing

Snap population and service points to road network

Now that we know the vertices of our transport network, we need to snap populations and hospitals to the nearest vertex. Alternatively (e.g. with network analyst in ARcGIS), the snapping can be done to the nearest edge. However, the cppRouting package uses vertices as the starting points for calculating isochrones.

Derive Isochrones

Having prepared our data for implementing isochrones, all that is left to be done is assign cost factors to roads, define network speeds (e.g. 5km/h for walking speed), and build a “network dataset”; that is, a transport network graph in this particular implementation.

Pre-isochrone input parameters

Road network graph - Dijkstra algorithm

Dijkstra algorithm graph. Data needs specific format to properly make graph. https://github.com/vlarmet/cppRouting#package-presentation

Isochrone example

Isochrones are catchment areas around points of interest which encompass all space reachable through the network at a given time budget and movement speed.

Isochrones use network distances which is preferable to euclidean distances (e.g. buffers). Network distances better model spatial reality and actual reachability, and take into account natural barriers (e.g. a river).

## tmap mode set to interactive viewing

Data frame for storing results

We will create a dataframe for storing the results of the 2SFCA analysis.

Run Isochrones on hospital and population locations

Now that we have the road position of every point of interest, we can create isochrones for that location.

## [1] 500
## [1] 1000
## [1] 1500
## [1] 2000
## [1] 2500
## [1] 3000
## [1] 3500
## [1] 4000

2SFCA analysis

Finally, we arrive to the reason why we are all here. 2SFCA implementation.

The preparatory steps are indespensible however, no matter the platform for implementation.

2SFCA - Step 1: Healthcare supply and demand at hospitals

We will calculate the supply-demand ratio at every hospital by dividing the a “supply capacity” with the total serviced population.

We will assume a per-doctor capacity of 24 patients in a day; and assign each hospital the arbitrary total of a 100 doctors. This data should ofcourse be informed and depending on your research can (and should) go into much detail; e.g. accessibility to dialysis, oncologists, respirators (Covid-19), etc.

Therefore, the daily healthcare supply is 2400 people per hospital.

2SFCA - Step 2: Population accessibility to healthcare

Having calculated the supply-demand ratios at hospitals, we will find out what is the 2SFCA spatio-temporal accessibility score at each population point.

This is the second step of the 2fa and includes finding out which hospitals are reachable from every population point, and then summing up the supply-demand ratios of reachable hospitals.

What we get is an accessibility score which represents how much healthcare capacity is accessible to a person living in a certain population point. Some population points might have no hospitals reachable in the given time budget! The 2SFCA score will be 0 in that case.

## [1] 500
## [1] 1000
## [1] 1500
## [1] 2000
## [1] 2500
## [1] 3000
## [1] 3500
## [1] 4000

Results interpretation

We successfully implemented the 2SFCA methodology in R and derived accessibility scores for each population point.

WE saved these scores in a dataframe which can be related to the original population dataset through primary keys. What we are interested in now is the spatial variation in accessibility scores, as well as overall scores for the city of Zurich.

## [1] "2SFCA scores at population points"
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00000 0.00000 0.09352 0.15050 0.18151 0.95758
## [1] "Supply-demand ratios at hospitals"
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.02295 0.03598 0.04368 0.05805 0.08076 0.12725

Results visualisation

We will map the accessibility scores for population points.

## tmap mode set to interactive viewing